import sys
from PyQt5.QtWidgets import (
    QApplication,
    QMainWindow,
    QWidget,
    QComboBox,
    QLineEdit,
    QPushButton,
    QMessageBox,
    QGridLayout,
    QLabel,
    QVBoxLayout,
    QHBoxLayout,
    QDialog,
)
from PyQt5.QtCore import pyqtSignal, pyqtSlot
from pydantic import ValidationError
from enum import Enum
from abc import ABC, abstractmethod, ABCMeta
from .c_lineEdit import LineEditFloat, LineEditInt, LineEditStr
import gui.controls.envs as envs
from . import message_box as MBox


# 创建一个新的元类来解决冲突
class MetaClass(type(QWidget), ABCMeta):
    pass


class CParams(QWidget, ABC, metaclass=MetaClass):
    before_save_signal = pyqtSignal(object)
    return_save_result_signal = pyqtSignal(object)

    def __init__(self, parent=None):
        super().__init__(parent)
        # 连接信号到自定义的处理方法
        self.before_save_signal.connect(self.before_save_handler)
        self.model = self.get_model()
        if self.model is None:
            raise ValueError("子类必须通过 get_model() 方法设置 model")
        self.gridLayout = QGridLayout()
        self.gridWidgets = dict()
        self.updateUI()

    @abstractmethod
    def get_model(self):
        """
        抽象方法：子类必须实现此方法来设置数据模型
        Returns:
            返回一个 Pydantic model 类
        """
        pass

    # @abstractmethod
    # def init_before_update(self):
    #     """子类必须实现：在updateUI之前的初始化操作"""
    #     pass

    # @abstractmethod
    # def init_after_update(self):
    #     """子类必须实现：在updateUI之后的额外设置"""
    #     pass

    def updateUI(self):
        fileds = self.model.model_fields
        for row, (field_name, field_info) in enumerate(fileds.items()):
            label = QLabel(field_info.description)
            self.gridLayout.addWidget(label, row, 0)
            if issubclass(field_info.annotation, Enum):
                self.gridWidgets[field_name] = QComboBox()
                self.gridWidgets[field_name].setMinimumWidth(100)
                self.gridWidgets[field_name].addItems(
                    [item.alias for item in list(field_info.annotation)]
                )
            else:
                field_type = field_info.annotation
                if field_type is float:
                    widget = LineEditFloat()
                elif field_type is int:
                    widget = LineEditInt()
                else:
                    widget = LineEditStr()
                widget.setPlaceholderText(f"请输入{field_info.description}")
                self.gridWidgets[field_name] = widget
            self.gridLayout.addWidget(self.gridWidgets[field_name], row, 1)
            # self.gridLayout.setColumnStretch(1, 1)
        self.setLayout(self.gridLayout)

    def before_save_handler(self):
        """
        这是一个可以在子类中重写的方法（也可以不重写）。
        如果子类没有重写这个方法，将不会调用这个方法。
        """
        # 在这里添加保存前的处理逻辑
        result = self.validateParams()
        # 重新发送信号，包含验证结果
        self.return_save_result_signal.emit(result)

    def validateParams(self, patch=None):
        try:
            field_values = {}
            for field_name, widget in self.gridWidgets.items():
                field_info = self.model.model_fields[field_name]
                if isinstance(widget, QComboBox):
                    enum_type = field_info.annotation
                    selected_text = widget.currentText()
                    enum_value = next(
                        (
                            item.value
                            for item in enum_type
                            if item.alias == selected_text
                        ),
                        None,
                    )
                    if not enum_value and field_info.is_required():
                        raise ValueError(f"字段 '{field_info.description}' 不能为空")
                    field_values[field_info.alias] = enum_value  # 使用 alias
                else:
                    text_value = widget.text().strip()
                    if not text_value and field_info.is_required():
                        raise ValueError(f"字段 '{field_info.description}' 不能为空")
                    field_values[field_info.alias] = text_value  # 使用 alias

            # 使用 pydantic 进行验证
            validated_data = self.model(**field_values)
            return validated_data.model_dump()

        except ValueError as e:
            # QMessageBox.warning(self, "警告", str(e))
            MBox.warning(str(e))
            return False
